在今年 9 月 10 號的時候,我看到 Flipper 官網發了一篇部落格是關於他們的韌體終於進入 1.0 版本了,也列出目前的版有的標誌性功能:
Firmware 1.0 Released
圖片來源:https://blog.flipper.net/released-firmware-1/
其中讓我比較感興趣的是發現他可以執行 JaveScript,於是就嘗試寫了一個簡單的 hello.js 嘗是在螢幕上印出 "Hello World",如下:
// helloWorld.js
console.log("Hello World");
但後來卻失敗了,也沒找到時間繼續嘗試,結果這幾天在 YT 看到 Derek Jamison 有一集是關於他訓練 GPT 去撰寫 Flipper 可以執行的 JS,於是有了今天的內容。
影片網址:https://youtu.be/5U26CU_j2tE?si=P1PENjpoujiw_-TA
請注意,透過 Flipper Zero 學習的資訊技術與知識,目的在於提升個人的技術能力和資安意識。我們強烈呼籲大家,絕對不要使用所學知識從事任何違法行為。您的合法使用是我們的期望,也是您自身責任的
一部分。
在剛剛提到的官方更新文章中,只有看到一段介紹:
圖片來源:https://blog.flipper.net/released-firmware-1/
JavaScript support is based on the mJS scripting engine. Originally designed for microcontrollers, mJS utilizes system resources efficiently and operates relatively quickly. It requires less than 50k of flash space and 2k of RAM.
前面有提到 script 資料夾下面有 examples 以及上面這段敘述有提到 Flipper 用的是 mJS,一種針對微控制器的腳本引擎,對系統資源的利用即為高效,執行速度也相對快。
簡單來說 mJS 就是很輕的 JS,特別適合 Flipper 這種記憶體和處理能力有限的裝置使用。
範例中包括像是 basusb_demo.js
:
let badusb = require("badusb");
let notify = require("notification");
let flipper = require("flipper");
let dialog = require("dialog");
badusb.setup({
vid: 0xAAAA,
pid: 0xBBBB,
mfr_name: "Flipper",
prod_name: "Zero",
layout_path: "/ext/badusb/assets/layouts/en-US.kl"
});
dialog.message("BadUSB demo", "Press OK to start");
if (badusb.isConnected()) {
notify.blink("green", "short");
print("USB is connected");
badusb.println("Hello, world!");
badusb.press("CTRL", "a");
badusb.press("CTRL", "c");
badusb.press("DOWN");
delay(1000);
badusb.press("CTRL", "v");
delay(1000);
badusb.press("CTRL", "v");
badusb.println("1234", 200);
badusb.println("Flipper Model: " + flipper.getModel());
badusb.println("Flipper Name: " + flipper.getName());
badusb.println("Battery level: " + to_string(flipper.getBatteryCharge()) + "%");
// Alt+Numpad method works only on Windows!!!
badusb.altPrintln("This was printed with Alt+Numpad method!");
// There's also badusb.print() and badusb.altPrint()
// which don't add the return at the end
notify.success();
} else {
print("USB not connected");
notify.error();
}
// Optional, but allows to interchange with usbdisk
badusb.quit();
總之就是跟一般的 JS 有一點差距,於是我們如果想用 ai 幫我寫一些 Flipper 能夠執行的腳本的話,需要先進行訓練。
其中 Derek 提供了一個他做的 GitHub Repo 可以幫助我們訓練 GPT 其中包含一段 intro.txt 以及三個 train.js,用法就是把 train.js 都丟給 GPT 然後放上 intro.txt 的描述後加上我們的需求例如下面的方式放上去:
其中 intro.txt
的內容如下:
Flipper Zero JavaScript is based on the mJS engine, which is fairly restricted. For example:
- You must use the `let` keyword. `const` and `var` are not allowed.
- You cannot do string interpolation with the `$`.
- You must use `let Math = require("math");` if you need access to any of the Math functions.
- You must use `to_string` to convert numerics (like integer and float) into a string.
- When keyboard.text display the on-screen keyboard, it covers the entire screen (so you can't see any previously printed information).
- All files are stored on the SD Card under the `/ext/` subdirectory.
- Delays are always measured in milliseconds and use the built-in `delay` function.
- Uint8Array(buffer) instead of `new Uint8Array(buffer)`. Objects like `String` do not exist. See arraybuf_to_string for code that should be used when converting a buffer into a string.
- There is no split or trim functions build in for strings. "1,2".split(","); and "x ".trim(); will generate runtime errors.
- See the training file for how to use the to_upper_case, to_lower_case, parse_int. You can get the ascii value of a character in a string using charCodeAt and also convert an ascii value back to a char using chr; see training file for details.
- Console.log prints to the serial port debugger, as an [I]nfo. Console.error prints to the serial port debugger, as an [E]rror. The print method writes to the Flipper display.
- Functions must be declared before they are used, but typically after all of the require statements.
Attached are three sample JavaScript files that work on the Flipper Zero.
You should only use functions defined in the training file, no additional built-in commands are supported. You should not redefine any function that is used in the training file.
在失敗幾次後,終於成功,他給我的檔案如下:
let widget = require("widget");
widget.show();
widget.addText(10, 10, "Primary", "Hello World");
// This line is optional; it keeps the widget open for 10 seconds.
delay(10000);
// Close the widget after showing the message.
widget.close();
執行結果:
成功!!
接著我們給他新任務,試著讀入使用者輸入:
mission: can you prompt for the name of the person then print "Hello !"
GPT 4o:
let widget = require("widget");
let keyboard = require("keyboard");
widget.show();
// Display on-screen keyboard to get user input
let name = keyboard.text("Enter your name");
// Display the "Hello <name>!" message on the screen
widget.addText(10, 10, "Primary", "Hello " + name + "!");
// Keep the widget open for 10 seconds
delay(10000);
// Close the widget after showing the message
widget.close();
結果如下:
結果大概重新試了十次還是一直遇到錯誤,好爛QQ
接著我們試著讓他寫一個 BasUSB 的腳本讓他去測試十個最常見的四位數 pin 碼:
結果是他還是會寫出許多錯誤,需要我們跟 GPT 來回 debug 3 ~ 5 次才會成功。
結論是 mJS 沒有想像中的方便,因為他其實不像是我們常用的 JS,如果透過 AI 協助的話確實會比較有效率,但還是需要先訓練而且經過多次 Debug 才有機會拿到可以執行的腳本。
今天的介紹就到這邊,這幾天準備開始寫 Flipper 的 APP 不知道大家有沒有什麼有趣的想法,歡迎留言告訴我。
明天見!